#ifndef Define_LcMotionAnalysis
#define Define_LcMotionAnalysis

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include "LcBasic.h"

class LcKLT
{
public:
	void work( vector< Mat > & frms , 
			   vector< vector< Point2f > >  & trajs);

	void work( vector< Mat > & frms,  Mat & trajs, vector<Point2f> * points = NULL);
	//mat interface

	void draw( Mat & dsp , vector< vector< Point2f > >  & trajs);

	void getGoodPoints( Mat & img, std::vector< Point2f > & points, int n);

	int veb;

	// image level tracking
	void track(
		const Mat & img1,
		const Mat & img2,
		vector<Point2f> & points1,
		vector<Point2f> & points2,
		vector< int > & selected_id,
		vector< int > & out_id);

private:

		static void checkGray( vector< Mat > & frms );

	//===========================

		

		//================================

		//all for tracking

		

		void track(
			const Mat & img1,
			const Mat & img2,
			vector<Point2f> & points1,
			vector<Point2f> & points2,
			vector< unsigned char > & status);

		void trackf2f(
			const cv::Mat & img1,
			const cv::Mat & img2,
			std::vector<Point2f> & points1,
			std::vector<Point2f> & points2,
			std::vector<unsigned char > & m_status,
			std::vector<float > * similarity = NULL);

		void normCrossCorrelation(
			 const Mat& img1,
			 const Mat& img2,
			 vector<Point2f>& points1,
			 vector<Point2f>& points2,
			 vector<float> & similarity,
			 vector<unsigned char> & status);

		static void append_fb_error(
			std::vector<Point2f> & point1,
			std::vector<Point2f> & point1p,
			std::vector<float> & fb_error);

		void filter_by_vector(std::vector<float> & a, float th, int dic,vector<unsigned char > & status);

		void filter_fb(std::vector<float> & fb_error, vector<unsigned char > & status);

		float fb_error_th;

		float similarity_th;

		void filter_sim(std::vector<float> & similarity,vector<unsigned char > & status);

		void subtraction( vector<unsigned char > & status,
						  std::vector < int > & sel_id ,
						  std::vector < int > & out_id );

		template< typename T>
		void __pick(std::vector<T>& a, std::vector<T>& b, std::vector<int> & id);

	//==========================
};

//==============================================================================

class LcProjRANSAC
{
public:
	virtual void work( Mat & trajs,
		vector< int> & inlier, vector<int> & outlier, vector<int> * base_id = NULL);

	int veb;

	void draw(Mat & img, vector< Point2f > points, vector< int> & inlier, vector<int> & outlier, vector<int> * base_id = NULL);
private:
	void rand_sel(int n,int m, std::vector<int> & sel);

	int countInliers(Mat & trajs ,Mat & P, float threshold,std::vector<bool> & status);
};

//==============================================================================


class LcLowRank: public LcProjRANSAC
{
public:
	void work( Mat & trajs,
		vector< int> & inlier, vector<int> & outlier, vector<int> * base_id = NULL);

	float alpha;

private:
	void shift_average( Mat & trajs, Mat & output);

	void updateF(Mat & F, Mat & phi,vector<int> &);
	void updateB(Mat & B, Mat & phi);

	void subtraction( vector<int> & id,vector<int> &  inlier,vector<int> &  outlier,int n);

	static void get_maxrows( Mat & src, int k, vector<int> & id);
	
};

//==============================================================================

#ifndef Define_LcColorSpaceType
#define Define_LcColorSpaceType

enum ColorSpaceType{
	LC_RGB,LC_LAB,LC_HSV
};

#endif

#include "Classifier.h"

class TrajPixelLabeling
{
public:

	void work( vector<Point2f> & points,
		       Mat & img,
			   vector<int> & inliers,
			   vector<int> & outliers,
			   Mat & output);

	TrajPixelLabeling( ColorSpaceType n_color_type= LC_RGB,
		               LcClassifier * n_classifier= new(LcKNN) )
	{ color_type = n_color_type; _classifier = n_classifier;}
private:

	LcClassifier* _classifier;
	ColorSpaceType color_type;

	void points2mat( vector<Point2f> &  points, Mat & mpo);

	void get_feature( Mat & img, Mat & feat);
	//vector<Point2f> * points
	
	void get_label( vector< int> & inlier, vector<int> & outlier, Mat & lab, int n);

	void draw_label( Mat & img, Mat & output);
};

//==============================================================================


//
//#include "MatchDescriptor.h"
//
//
//class LcStablization
//{
//public:
//	void work( vector<Mat>& frms , Mat & likelihood);
//
//private:
//
//	void getHs( vector<Mat> & frms , vector<Mat > & Hs );
//
//	void getProj( vector< Mat > & frms,
//		      vector< Mat > & Hs,
//			  vector< Mat > & proj_frms,
//			  vector< Mat > & weight_frms);
//
//	void buildModel( vector< Mat > & proj_frms,
//					 vector< Mat > & weight_frms,
//					 Mat & mean, Mat & std);
//
//	void getLikelihood( Mat & mean, Mat & std,
//						Mat & img , Mat & likelihood);
//
//
//};



//==============================================================================
//#include "VideoRead.h"
//
//void testStablization();
//
//void testKLT();
//
//void testProjRANSAC();
//
//void testLowRank();

#endif